package com.sheng.leetcode.year2024.month02.day05;

import org.junit.Test;

import java.util.ArrayDeque;
import java.util.Deque;

/**
 * @author by ls
 * @date 2024/2/5
 * <p>
 * 1696. 跳跃游戏 VI<p>
 * <p>
 * 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。<p>
 * 一开始你在下标 0 处。每一步，你最多可以往前跳 k 步，但你不能跳出数组的边界。<p>
 * 也就是说，你可以从下标 i 跳到 [i + 1， min(n - 1, i + k)] 包含 两个端点的任意位置。<p>
 * 你的目标是到达数组最后一个位置（下标为 n - 1 ），你的 得分 为经过的所有数字之和。<p>
 * 请你返回你能得到的 最大得分 。<p>
 * <p>
 * 示例 1：<p>
 * 输入：nums = [1,-1,-2,4,-7,3], k = 2<p>
 * 输出：7<p>
 * 解释：你可以选择子序列 [1,-1,4,3] （上面加粗的数字），和为 7 。<p>
 * <p>
 * 示例 2：<p>
 * 输入：nums = [10,-5,-2,4,0,3], k = 3<p>
 * 输出：17<p>
 * 解释：你可以选择子序列 [10,4,3] （上面加粗数字），和为 17 。<p>
 * <p>
 * 示例 3：<p>
 * 输入：nums = [1,-5,-20,4,-1,3,-6,-3], k = 2<p>
 * 输出：0<p>
 * <p>
 * 提示：<p>
 * 1 <= nums.length, k <= 10^5<p>
 * -10^4 <= nums[i] <= 10^4<p>
 */
public class LeetCode1696 {

    @Test
    public void test01() {
//        int[] nums = {1, -1, -2, 4, -7, 3};
//        int k = 2;
//        int[] nums = {10, -5, -2, 4, 0, 3};
//        int k = 3;
        int[] nums = {1, -5, -20, 4, -1, 3, -6, -3};
        int k = 2;
        System.out.println(new Solution().maxResult(nums, k));
    }
}

class Solution {
    public int maxResult(int[] nums, int k) {
        // 一共要跳几步未定，最多跳跃 n 次，即每次跳一步
        int n = nums.length;
        // 到达对应下标的最大得分
        int[] ints = new int[n];
        Deque<Integer> deque = new ArrayDeque<>();
        deque.offer(0);
        for (int i = 0; i < n; i++) {
            // 判断是否超出了 k 的范围
            if (i - deque.peekFirst() > k) {
                deque.pollFirst();
            }
            // 更新
            ints[i] = nums[i] + ints[deque.peekFirst()];
            // 循环判断
            while (!deque.isEmpty() && ints[deque.peekLast()] <= ints[i]) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        return ints[n - 1];
    }
}
